/**
* file name  : GetPHASE.java
* authors    : Luciano Xumerle
* created    : ven 12 ago 2005 17:10:48 CEST
*
* Copyright (c) 2004-2005 Luciano Xumerle. All rights reserved.
*
* This file is part of gephinfo.
*
* gephinfo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.

*
*/

package it.ciano.jenoware;

import java.util.HashMap;
import it.ciano.util.CFile;

/**
 * The class GetPHASE provides methods to create an input file compatible
 * with the PHASE program.
 * You must use method setCaseControl to create a file compatible with the
 * PHASE -c option. Default produced file has no case-control info.
 *
 * @author Luciano Xumerle
 * @version 0.0.1
 */
public class GetPHASE extends GetFile
{

    //
    // private vars used to store the field names
    //
    private String geno[];
    private String basep[];
    private boolean _case_control;

    //
    // stores null allele value foreach marker
    //
    HashMap nulls;

    /**
     * Class Constructor.
     *
     * @param pedigree a populated Pedigree object.
     * @param bp array of marker positions expressed in basepairs.
     */
    public GetPHASE ( Pedigree pedigree, String[] bp )
    {
        this ( pedigree, bp, null );
    }

    /**
     * Class Constructor.
     *
     * @param pedigree a populated Pedigree object.
     * @param bp array of marker positions expressed in basepairs.
     * @param genoOrder ordered list of markers.
     */
    public GetPHASE ( Pedigree pedigree, String[] bp, String[] genoOrder )
    {
        super ( pedigree );
        setFilename ( "PHASEdata" );
        basep = bp;
        _case_control = false;
        if ( genoOrder == null )
            geno = getPed().getMarkersList();
        else
            geno = genoOrder;
        setNullValue();
    }

    /**
     * Set the class to produce a file compatible with the option -c oh the PHASE program.
     */
    public void setCaseControl()
    {
        _case_control = true;
    }

    /**
     * Overriding toString method
     *
     * @return all informations that will be contained into the destination files.
     */
    public String toString()
    {
        if ( geno.length != basep.length )
            return "";
        StringBuffer res = new StringBuffer();
        Sbj id[] = getPed().getListSbj();
        // append number of subject
        res.append ( id.length );
        res.append ( "\n" );
        // append number of loci
        res.append ( geno.length );
        res.append ( "\n" );
        // append positions expressed into basepairs
        res.append ( "P" );
        for ( int i = 0; i < basep.length; i++ )
        {
            res.append ( " " );
            res.append ( basep[ i ] );
        }
        res.append ( "\n" );
        // append type of markers
        for ( int i = 0; i < geno.length; i++ )
            if ( nulls.containsKey ( geno[ i ] ) && ( ( String ) nulls.get ( geno[ i ] ) ).equals ( "-1" ) )
                res.append ( "M" );
            else
                res.append ( "S" );
        res.append ( "\n" );
        // append subjectb data
        for ( int s = 0; s < id.length; s++ )
        {
            // append case or control symbol
            if ( _case_control )
            {
                String _case = "1 ";
                String _control = "0 ";
                if ( id[ s ].isCase() )
                    res.append ( _case );
                else
                    res.append ( _control );
            }
            // append id
            res.append ( id[ s ].getID() );
            res.append ( "\n" );
            // buffer used to store the two allele lines
            StringBuffer geno1 = new StringBuffer();
            StringBuffer geno2 = new StringBuffer();
            for ( int i = 0; i < geno.length; i++ )
            {
                Genotype mm = id[ s ].getGenotype ( geno[ i ] );
                if ( mm.isValid() )
                {
                    geno1.append ( mm.getAll1() );
                    geno2.append ( mm.getAll2() );
                }
                else
                {
                    geno1.append ( ( String ) nulls.get ( geno[ i ] ) );
                    geno2.append ( ( String ) nulls.get ( geno[ i ] ) );
                }
                geno1.append ( " " );
                geno2.append ( " " );
            }
            res.append ( geno1.toString() );
            res.append ( "\n" );
            res.append ( geno2.toString() );
            res.append ( "\n" );
        }
        return res.toString();
    }

    /**
     * Creates all the expected files.
     *
     * @return true if all operations are ok.
     */
    public boolean createsFile()
    {
        return CFile.saveString ( getFilename() + ".inp", toString() );
    }


    // PRIVATE METHODS // PRIVATE METHODS // PRIVATE METHODS // PRIVATE METHODS //
    // PRIVATE METHODS // PRIVATE METHODS // PRIVATE METHODS // PRIVATE METHODS //
    // PRIVATE METHODS // PRIVATE METHODS // PRIVATE METHODS // PRIVATE METHODS //

    /**
     * Sets the nulls HashMap
     */
    final private void setNullValue()
    {
        nulls = new HashMap();
        for ( int i = 0; i < geno.length; i++ )
        {
            MarkerFreq mf = new MarkerFreq ( getPed(), geno[ i ] );
            Allele[] tt = mf.getOrderedAlleleList();
            if ( tt.length > 2 )
                nulls.put ( geno[ i ], "-1" ); // microsatellite missing value
            else if ( tt.length == 2 )
                nulls.put ( geno[ i ], "?" ); // SNP missing value
        }
    }




} // end class

